﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace OverStore.Runtime.ObjectRepository
{
    /// <summary>
    /// Registers objects of type <typeparamref name="TEntity"/> and counts registrations.
    /// </summary>
    /// <typeparam name="TEntity">Type of entity.</typeparam>
    public sealed class RefCounter<TEntity>
        where TEntity : class
    {
        private readonly IDictionary<TEntity, int> _RefCounter = new Dictionary<TEntity, int>(ReferenceEqualityComparer<TEntity>.Instance);

        /// <summary>
        /// Increments internal reference counter assosiated with specified entity.
        /// Method returns number of times entity was referenced minus number of times entity was released.
        /// If entity is referenced firts time, method returns 1.
        /// </summary>
        public int Touch(TEntity entity)
        {
            if (Object.ReferenceEquals(entity, null))
                throw new ArgumentNullException("entity");
            int count = 0;
            _RefCounter.TryGetValue(entity, out count);
            count++;
            _RefCounter[entity] = count;
            return count;
        }

        /// <summary>
        /// Decrements internal reference counter assosiated with specified entity.
        /// Method returns number of times entity was referenced minus number of times entity was released.
        /// </summary>
        public int Untouch(TEntity entity)
        {
            if (Object.ReferenceEquals(entity, null))
                throw new ArgumentNullException("entity");
            int count = 0;
            _RefCounter.TryGetValue(entity, out count);
            count--;
            _RefCounter[entity] = count;
            return count;
        }

        /// <summary>
        /// Clear all references to specified entity.
        /// </summary>
        public void Reset(TEntity entity)
        {
            if (Object.ReferenceEquals(entity, null))
                throw new ArgumentNullException("entity");
            _RefCounter.Remove(entity);
        }

        /// <summary>
        /// Reset reference counter for all entities.
        /// </summary>
        public void Clear()
        {
            _RefCounter.Clear();
        }
    }
}
